require('js/lib/require_patch').monkeypatch(this); // android needs this. Apparently there are different contexts

var ui = require('js/ui/common/ui');

/*
 * Our custom test view component takes an initial
 * parameters that make up the test, and will be stored 
 * in an external database 
 * 
 */
function TestView(params) {
	globals.util.debugDump('TestView params', params);
	
	//create and populate the test object
	var instance = ui.view({
		backgroundColor: '#000'
	});
	
	var title = params.title || '';
	
	var defaultFontSize = Math.floor(params.defaultFontSize||14 * globals.deviceFactor);
	var defaultLabelHeight = params.defaultLabelHeight * globals.deviceFactor || 85 * globals.deviceFactor;
								
	var controlMap = ['fn', 'fp', 'dp', 'dn']; // Controls mapping to location: 
	var controls = [];	// another instance variable to hold the test result
	var currentTest = params.selected;  // State of currently selected result
	var selectedCondition = {};  // Used to store an additional processing contition, if needed
					
	var textValue = ui.label(title, {
		height:defaultLabelHeight,
		width:'auto',
		left:5, right:5,
		color:'BLACK',
		font: {
			fontSize:defaultFontSize
		}
	});
	var testSelector = ui.view({
		top: defaultLabelHeight/4,
		size: {width: 200 * globals.deviceFactor, height: defaultLabelHeight},
		backgroundImage: globals.util.urls()['bg_clear'],
		borderWidth: 2 * globals.deviceFactor,
		borderRadius: 5 * globals.deviceFactor,
		borderColor: 'BLACK'
	});
	testSelector.add(textValue);
	testSelector.addEventListener('click', function(e){
		manageBreakout(currentTest);
	});
	var labelContainer = ui.view({top: 20 * globals.deviceFactor,
		height: defaultLabelHeight + defaultLabelHeight/2});
	labelContainer.add(testSelector);
	instance.add(labelContainer);
	
	if (params.result && params.result.providerId) {
		var lastResultContainer = ui.view({height: defaultLabelHeight, top: 110 * globals.deviceFactor});
		var provider = globals.db.listProviders('id = ?',params.result.providerId)[0];
		var text = 'Last Test Results entered by: ' + provider.fullName() + ' on ' + globals.util.getDateFromStr(params.result.testDate).toDateString();
		var resultLabel = ui.label(text,{color:'#fff', textAlign: 'center'});
		lastResultContainer.add(resultLabel);
		instance.add(lastResultContainer);
	}
	
	// Closure to access/update state of the test selector
	instance.addEventListener('controlSelected', function(e){
		currentTest = e.currentValue;
		manageTestSelector(e);
	});
	
	var buttonGrid = {layout: 'horizontal', size: {width: 200 * globals.deviceFactor, height: 60 * globals.deviceFactor}, top: 180 * globals.deviceFactor};
	if (params.condition) {
		buttonGrid.left = "50%";
		var conditionView = ui.view({
				width:'45%', left:'2%', height: 120 * globals.deviceFactor, top: 180 * globals.deviceFactor, 
				layout:'vertical', backgroundColor:'#8DA0B6', borderRadius:4});
		conditionView.add(ui.label(params.condition.title,{top: 10 * globals.deviceFactor, textAlign:'center', color:'#fff',font: {fontFamily:ui.fontFamily,fontSize:defaultFontSize}}));
		if (params.condition.control) {
			var conditionControl;
			switch(params.condition.control) {
				case 'switch':
					selectedCondition = "false";
					conditionControl = Ti.UI.createSwitch({top: 30 * globals.deviceFactor, value: false, height:30 * globals.deviceFactor});
					conditionControl.addEventListener('change',function(e){
						selectedCondition = e.value ? "true" : "false";
					});
					break;
				case 'textField':
					conditionControl = Titanium.UI.createTextArea({
					    height:20 * globals.deviceFactor,
					    width:30 * globals.deviceFactor,
					    top:30 * globals.deviceFactor,
					    font:{fontSize:28,fontFamily:ui.fontFamily, fontWeight:'bold'},
					    color:'#888',
					    textAlign:'left',
					    keyboardType:Titanium.UI.KEYBOARD_PHONE_PAD,
					    borderWidth:2,
					    borderColor:'#bbb',
					    borderRadius:5
					});
					conditionControl.addEventListener('change',function(e){
						if (params.condition.range) {
							if (e.value >= params.condition.range[0] && e.value <= params.condition.range[1]) {
								selectedCondition = "true";
							}
							else {
								selectedCondition = "false";
							}
						}
					});
					break;
			}
			conditionView.add(conditionControl);
		}
		instance.add(conditionView);
	}
	var controlLine1 = ui.view(buttonGrid);
	buttonGrid.top = buttonGrid.top + 70 * globals.deviceFactor;
	var controlLine2 = ui.view(buttonGrid);
	
	//Create the necessary view structures to represent the
	//current value of the test
	for (var i = 0; i < 4; i++) {
		// Reset all off
		var fg = ui.label(controlMap[i], 
			{height:25 * globals.deviceFactor, 
			 width:25 * globals.deviceFactor, 
			 textAlign:'center',
			 font: {fontFamily:ui.fontFamily, fontSize: 12 * globals.deviceFactor}});

		var control = ui.image({
			height:50 * globals.deviceFactor,
			width:50 * globals.deviceFactor,
			left:35 * globals.deviceFactor
		});
		control.add(fg);
		
		(function() {
			//we need to capture the value of "state"
			//for use in click handler functions
			//on our image views.  To do this, we
			//use a closure (this self-calling function)
			var state = { type: controlMap[i], parent: instance };

			control.addEventListener('click', function() {
				setControl(state);
			});
		})();
		
		controls.push(control);
		i < 2 ? controlLine1.add(control) : controlLine2.add(control);
		
	}
	
	instance.add(controlLine1);
	instance.add(controlLine2);

	// Control Bar
	var controlLabels = {back: params.primary?'Tests':'Back'};
	var controlFunctions = {back: function() { 
			saveResults(params.id);
			instance.fireEvent('dismiss.test', {id: params.id}); 
		}};
	if (params.nextTest) {
		Ti.API.debug('Adding next test control');
		controlLabels.next = 'Next';
		controlFunctions.next = function() { 
			saveResults(params.id);
			instance.fireEvent('next.test', {next: params.nextTest}); 
		}
	}
	if (params.winTrail) {
		controlLabels.home = 'Exit';
		controlFunctions.home = function() { 
			saveResults(params.id);
			var win = params.winTrail.pop();
			while(win) {
				win.close();
				win = params.winTrail.pop();
			}
		}
	}
	var controlView = ui.controlBar(controlLabels,controlFunctions,{bottom: 0});
	instance.add(controlView);
	
	instance.addManagedWin = function(win) {
		if (!params.winTrail) {
			params.winTrail = [];
		}
		
		params.winTrail.push(win);
	}
			
	//initialize view and return instance
	setControl({ type: params.selected, parent: instance }); 
	return instance;
	
	//inner function to update view to reflect the current
	//test
	function setControl(state) {
		var selector = getIndexForType(state.type);
		
		Ti.API.debug('++++ Selected:' + selector + " Prior: " + state.parent.selected);	

		for (var i = 0, l = controlMap.length; i < l; i++) {
			if (i === 0) {
				if (selector == i && state.parent.selected !== state.type) {
					controls[i].image = globals.images['stop'];
				} else {
					controls[i].image = globals.images['stop_off'];
				}
			}
			else if (i > 0 && i < 3) {
				if (selector == i && state.parent.selected !== state.type) {
					controls[i].image = globals.images['yield'];
				} else {
					controls[i].image = globals.images['yield_off'];
				}
			}
			else {
				if (selector == i && state.parent.selected !== state.type) {
					controls[i].image = globals.images['go'];
				} else {
					controls[i].image = globals.images['go_off'];
				}
			}
		}
		
		state.parent.selected = state.parent.selected === state.type ? '' : state.type;

		// Notification to manage other parts of the view				
		if (state.type) {
			instance.fireEvent('controlSelected',{
				currentValue: state.type,
				lastSelected: state.parent.selected
			});
		}
	}
	
	function getIndexForType(type) {
		for (var i=0, l=controlMap.length; i < l; i++) {
			if (type === controlMap[i])
				return i;
		}
	}
	
	function manageTestSelector(e) {
		var type = e.currentValue;
		var selected = e.lastSelected;
		Ti.API.debug('Type: ' + type + 
				' Selected: ' + selected + 
				' Label: ' + textValue.text + 
					' is {weight:' + textValue.font.fontWeight + ',size:'+textValue.font.fontSize+'}');
		testSelector.backgroundImage = globals.util.urls()['bg_clear'];
		testSelector.backgroundColor = 'GRAY';
		testSelector.borderColor = 'BLACK';
		textValue.font = { fontWeight: 'normal', fontSize: defaultFontSize};
		textValue.color = 'BLACK';

		if (!type || !selected) {
			return;
		}
		
		testSelector.backgroundImage = globals.util.urls()['bg_gradient'];
		
		var i = getIndexForType(type);	// ['fn', 'fp', 'dp', 'dn']
		// Manage state of test selector
		if (params.primary) {
			if (i == 3) {
				Ti.API.debug(type + ' should be "dn"');
				textValue.font = { fontWeight: 'bold', fontFamily: ui.fontFamily, fontSize: defaultFontSize };
				testSelector.borderColor = 'YELLOW';
				testSelector.backgroundImage = globals.util.urls()['bg_gradient'];
			}
			else {
				textValue.color = 'GRAY';
				textValue.font = { fontWeight: 'normal', fontFamily: ui.fontFamily, fontSize: defaultFontSize };
				testSelector.borderColor = 'BLACK';
				testSelector.backgroundImage = globals.util.urls()['bg_clear'];
			}
			
			if (i < 3 && i > 0) {
				testSelector.borderColor = 'RED';				
			}
			
			globals.results = []; // Initialize stack of breakout path
			// Immediately show breakout, if selected
			if (type == 'dn') {
				manageBreakout(type);
			}
		}
		else {
			// For Breakout, color border based on Treatment color
			testSelector.backgroundImage = globals.util.urls()['bg_gradient'];
			var breakout = params[type+'Test'];
			if (breakout.borderColor)
				testSelector.borderColor = breakout.borderColor;
		}
	}
	
	function saveResults(testId) {
		if (instance.selected && instance.selected != '') {
			Ti.API.debug('Saving patient_id: '+globals.patient.id+' provider: '+globals.provider.id+' test: ' + testId + ' result: ' + instance.selected + ' using timestamp value: ' + globals.db.timeStamp());
			var PatientTest = require('js/model/PatientTest');
			var result = new PatientTest({
				patient_id:globals.patient.id, 
				provider_id:globals.provider.id, 
				test_id:testId, 
				result:instance.selected, 
				test_date: globals.db.timeStamp(),
				appointment_id: globals.appointment.id
			});
			globals.db.addPatientTests(result);
			
			return result;
		}
		
		return null;
	}

	function manageBreakout(selected) {
		var breakout = params[selected + 'Test'];
		// A condition may change the path
		if (selectedCondition && breakout && breakout[selectedCondition]) {
			breakout = breakout[selectedCondition];
		}
		if (breakout) {
			var result = saveResults(params.id);
			result.test = params;
			globals.results.push(result);
			globals.util.debugDump('manageBreakout '+selected + 'Test', breakout);
			if (breakout.tests) {
				var result = globals.db.listPatientTestResults(globals.patient.id, breakout.tests);
				var newParams = globals.util.objectMerge(result,
					{
				    	title: params.category.name + ': ' + result.name,
				    	category: params.category,
				    	selected: result.result.result,
				    	winTrail: params.winTrail || []
					});
			}
			// Prepare treatment dialog
			if (breakout.treatments) {
				var treatment = globals.db.listTreatments('id = ?',[breakout['treatments']])[0];
				if (newParams) {
					treatment.nextTest = newParams;
				}
				treatment.winTrail = params.winTrail;
				var TreatmentWin = require('js/ui/TreatmentWin');
				var treatmentWin = new TreatmentWin(treatment);
				
				treatmentWin.open();
			}
			else {
				var UtilityWindow = require('js/ui/UtilityWindow');
				var SettingsView = require('js/ui/SettingsView');
				var tv = new TestView(newParams);
				var win = new UtilityWindow('Breakout Test', tv, new SettingsView(), {backgroundImage: 'images/grain.png'});
				tv.addManagedWin(win);
				win.open();
				
				tv.addEventListener('dismiss.test', function(e){
					win.close();
				});
			}
		}
		else {
			if (params.primary && (selected === 'fp' || selected === 'dp')) {
				var alertDialog = Titanium.UI.createAlertDialog({
				    title: 'Treat Pain',
				    message: 'Treat pain prior to breakout',
				    buttonNames: ['OK']
				});
				alertDialog.show();		
			}
		}
	}
};

//Public Module API
exports.TestView = TestView;